/**
 * @brief    频响分析测试
 *
 * @version  0.1
 * @author   wjw
 * @date     2025.04.11
 *         _
 *     ___| |__   ___ _ __   __ _  ___  _ __   __ _
 *    / __| '_ \ / _ \ '_ \ / _` |/ _ \| '_ \ / _` |
 *    \__ \ | | |  __/ | | | (_| | (_) | | | | (_| |
 *    |___/_| |_|\___|_| |_|\__, |\___/|_| |_|\__, |
 *                          |___/             |___/
 * @copyright (c) 2025 by 神工仿真, All Rights Reserved.
 */
#pragma once
#include "gtest/gtest.h"

#include "DBManager/IService/Input/Dynamic/IFREQ1Service.h"

#include "../FrequencyModeSolver.h"
#include "SGFem/Task/Kernel/MModel.h"

using SG::DataStructure::Common::Status;
using SG::DataStructure::FEM::Project;
using namespace SG::DBManager;

extern std::shared_ptr<DBServiceFactory> DB_SERVICEFACTORY;

struct FrequencyModeTestData
{
    std::string                   m_inputFile;    ///< 输入文件名称
    std::vector<double>           m_modalTarget;  ///< Nastran响应结果
    SG::Algebra::Real_t           m_error;        ///< 误差上限
    SG::DataStructure::Common::Id m_ForceID;      ///< 载荷作用点全局ID
};

class FrequencyMOdeTest : public ::testing::TestWithParam<FrequencyModeTestData>
{
  protected:
    void SetUp () override
    {
        modelPath = getTestDataPath ("SGFem/ModalAnalysis/");
    }

    void TearDown () override
    {
        DB_SERVICEFACTORY->ClearDatabase ();
    }
    std::string modelPath;  ///< 输入模型文件路径
};

TEST_P (FrequencyMOdeTest, ComputeResponseAsExpect)
{
    auto para = GetParam ();
    // Input
    Project project;
    project.m_modelFilePath = modelPath;
    project.m_modelFileName = para.m_inputFile;
    auto posi               = para.m_inputFile.find ('.');
    project.m_jobName       = para.m_inputFile.substr (0, posi);

    DB_SERVICEFACTORY->ClearDatabase ();
    SG::Import::SGImporter importer (DB_SERVICEFACTORY);
    auto                   status = importer.Import (project.m_modelFilePath + project.m_modelFileName);
    ASSERT_EQ (status, Status::STATUS_Success);

    // 获取模型中所有的subCase
    auto                            subcaseIds = DB_SERVICEFACTORY->get<ISubcaseService> ()->GetAllSubcaseID ();
    auto                            para1      = DB_SERVICEFACTORY->get<ISubcaseService> ()->FindSubCase (subcaseIds[0]);
    SG::DataStructure::FEM::Subcase subcase (para1);

    FrequencyModeSolver solver;
    solver.Solve (DB_SERVICEFACTORY, project, subcaseIds[0]);

    // Test data
    Kernel::MModel ModelTest (SG::DataStructure::FEM::SOLType::SOL_SEMFREQ, DB_SERVICEFACTORY);
    std::vector<SG::DataStructure::FEM::FREQ1Data> FREQ1Data;
    ASSERT_EQ (Status::STATUS_Success, DB_SERVICEFACTORY->get<IFREQ1Service> ()->FindBySId (subcase.GetFrequencyId (), _OUT FREQ1Data));

    SG::Algebra::ComplexVec_t V;
    std::vector<double>       wSet = getfreqVector(FREQ1Data);
    std::vector<double>       modalTest;  // 将存储复数的幅值

    for (const auto& w : wSet)
    {
        ModelTest.GetDisplacement (subcaseIds[0], w, _OUT V);

        // 计算复数的幅值 (magnitude/absolute value)
        double magnitude = std::abs (V (para.m_ForceID));
        modalTest.push_back (magnitude);
    }

    // Target data
    const auto modalTarget = para.m_modalTarget;

    // Check 计算相对误差
    double numerator_norm   = 0.0;
    double denominator_norm = 0.0;
    double diff;
    for (size_t i = 0; i < modalTest.size (); ++i)
    {
        diff = modalTest[i] - modalTarget[i];
        numerator_norm += diff * diff;
        denominator_norm += modalTarget[i] * modalTarget[i];
    }
    numerator_norm        = std::sqrt (numerator_norm);
    denominator_norm      = std::sqrt (denominator_norm);
    double relative_error = numerator_norm / denominator_norm;
    ASSERT_LE (relative_error, para.m_error);
};

std::vector<double> TargetModal1 = {
    6.981323E-04, 6.290223E-04, 5.431595E-04, 4.643196E-04, 3.992414E-04, 3.471937E-04, 3.056469E-04, 2.721703E-04, 2.448415E-04,
    2.222241E-04, 2.032595E-04, 1.871656E-04, 1.733586E-04, 1.613973E-04, 1.509438E-04, 1.417359E-04, 1.335676E-04, 1.262751E-04,
    1.197269E-04, 1.138158E-04, 1.084545E-04, 1.035703E-04, 9.910300E-05, 9.500181E-05, 9.122387E-05, 8.773271E-05, 8.449711E-05,
    8.149016E-05, 7.868861E-05, 7.607222E-05, 7.362332E-05, 7.132640E-05, 6.916781E-05, 6.713548E-05, 6.521869E-05, 6.340789E-05,
    6.169456E-05, 6.007107E-05, 5.853054E-05, 5.706682E-05, 5.567429E-05, 5.434792E-05, 5.308311E-05, 5.187567E-05, 5.072180E-05,
    4.961803E-05, 4.856117E-05, 4.754829E-05, 4.657672E-05, 4.564397E-05, 4.474778E-05, 4.388603E-05, 4.305680E-05, 4.225826E-05,
    4.148875E-05, 4.074673E-05, 4.003074E-05, 3.933944E-05, 3.867157E-05, 3.802598E-05, 3.740155E-05, 3.679728E-05, 3.621219E-05,
    3.564540E-05, 3.509606E-05, 3.456337E-05, 3.404659E-05, 3.354502E-05, 3.305800E-05, 3.258490E-05, 3.212515E-05, 3.167817E-05,
    3.124345E-05, 3.082048E-05, 3.040881E-05, 3.000798E-05, 2.961756E-05, 2.923717E-05, 2.886643E-05, 2.850495E-05, 2.815241E-05,
    2.780848E-05, 2.747284E-05, 2.714520E-05, 2.682528E-05, 2.651281E-05, 2.620753E-05, 2.590919E-05, 2.561757E-05, 2.533243E-05,
    2.505357E-05, 2.478078E-05, 2.451386E-05, 2.425262E-05, 2.399689E-05, 2.374650E-05, 2.350127E-05, 2.326106E-05, 2.302570E-05,
    2.279505E-05, 2.256898E-05
};
SG::Algebra::Real_t           errorModal1   = 0.037971;
SG::DataStructure::Common::Id ForceIDModal1 = 344;
INSTANTIATE_TEST_CASE_P (ModalFrequencyAnalysis,
                         FrequencyMOdeTest,
                         testing::Values (FrequencyModeTestData{
                              "ModalFrequedcyModel.bdf", TargetModal1, errorModal1, ForceIDModal1 }));